package com.oitsm.init;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;


/**
 * 顺序初始化管理器
 * @author Arab Runner
 * Jun 18, 2011 11:38:17 AM
 */
public class InitManager implements ApplicationContextAware{
	private static ApplicationContext context;
	
	private List<String> initableBeans = new ArrayList<String>();
	
	public void setInitableBeans(List<String> initableBeans) {
		this.initableBeans = initableBeans;
	}

	public void setApplicationContext(ApplicationContext context)
			throws BeansException {
		InitManager.context = context;
	}
	
	public void initialize(){
		for(String v : initableBeans){
			long start = System.currentTimeMillis();
			System.out.println("#init start-->" + v+" ...");
			InitBean initBean = decodeInitBean(v);
			if(initBean.getType() == InitBean.TYPE_BEAN){
				beanInit(initBean.getName());
			}else if(initBean.getType() == InitBean.TYPE_STATIC){
				staticClassInit(initBean.getName());
			}else if(initBean.getType() == InitBean.TYPE_STATIC_NEED_SESSION){
				staticBDClassInit(initBean.getName());
			}
			System.out.println("#init end-->" + v+",used time:"+(System.currentTimeMillis()-start)+"ms");
		}
	}
	
	/**
	 * 静�?�初始化
	 * @param className
	 */
	@SuppressWarnings({ "unchecked" })
	public void staticClassInit(String className){
		try{
			Class tClass = Class.forName(className);
			Method initMethod = null;
			initMethod = tClass.getMethod("init");
			initMethod.invoke(tClass);
		}catch(Exception e){
			System.out.println("#static init failure,class name:"+className+",err:"+e.getMessage());
		}
	}
	
	/**
	 * @param className
	 */
	@SuppressWarnings("unchecked")
	public void staticBDClassInit(String className){
		Session session = null;
		try{
			Class tClass = Class.forName(className);
			Method initMethod = null;
			initMethod = tClass.getMethod("init",Session.class);
			if(context.containsBean("sessionFactory")){
				SessionFactory sf = (SessionFactory)context.getBean("sessionFactory");
				session = sf.openSession();
				initMethod.invoke(tClass,session);
			}else{
				System.out.println("#staticDB init failure,class name:"+className+",err:no session factory was found!");
			}
		}catch(Exception e){
			e.printStackTrace();
			System.out.println("#staticDB init failure,class name:"+className+",err:"+e.getMessage());
		}finally{
			if(session!=null){
				session.close();
			}
		}
	}
	
	/**
	 * @param beanName
	 */
	public void beanInit(String beanName){
		try{
			if(context.containsBean(beanName)){
				Object bean = context.getBean(beanName);
				if(bean instanceof Initable){
					Initable initable = (Initable)bean;
					initable.init();
				}else{
					System.out.println("#bean init failure,bean name:"+beanName+",err:bean not instanceof Initable!");
				}
			}else{
				System.out.println("#bean init failure,bean name:"+beanName+",err:no such bean!");
			}
		}catch(Exception e){
			e.printStackTrace();
			System.out.println("#bean init failure,bean name:"+beanName+",err:"+e.getMessage());
		}
	}
	
	private InitBean decodeInitBean(String config){
		String[] splits = config.split(":");
		if(splits.length == 1){
			return new InitBean(InitBean.TYPE_BEAN,splits[0]);
		}else{
			String typeStr = splits[0];
			int type = 0;
			if("bean".equals(typeStr)){
				type = InitBean.TYPE_BEAN;
			}else if("static".equals(typeStr)){
				type = InitBean.TYPE_STATIC;
			}else if("staticDB".equals(typeStr)){
				type = InitBean.TYPE_STATIC_NEED_SESSION;
			}
			return new InitBean(type,splits[1]);
		}
	}
	
}
